/**
 * Copyright 2012 Roger Cockshutt
 * krakenbrau@gmail.com
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.googlecode.parallelrl.display;


import com.googlecode.blacken.colors.ColorPalette;
import com.googlecode.blacken.swing.SwingTerminal;
import com.googlecode.blacken.terminal.CursesLikeAPI;
import com.googlecode.blacken.terminal.UnboundTerminal;
import com.googlecode.parallelrl.Config;
import com.googlecode.parallelrl.ParallelRL;

/**
 * @author Roger Cockshutt
 *
 * The Screen class is the base display class.  While not technically a View, it is essential to (and only used by) View objects.
 */
public final class Screen {
	
	// --------- Singleton ----------- //
	private static Screen instance = null;
	
	private Screen() {}
	
	public static Screen get() {
		if (instance == null) {
			instance = new Screen();
		}
		
		return instance;
	}
	// ------------------------------- //
	
	
	
	private CursesLikeAPI	terminal = null;
	private CursesLikeAPI	buffer = null;
	private ColorPalette		palette =	null;
	private Integer defaultBg = Colors.libTCOD.black.normal;
	private Integer defaultFg = Colors.libTCOD.white.normal;
	
	
	
	/**
	 * Set up the TerminalInterface.  Currently, the TerminalInterface is instantiated as
	 * SwingTerminal.  The ColorPalette is created and assigned to the TerminalInterface.
	 * 
	 * @param ySize Terminal size in rows.
	 * @param xSize Terminal size in columns.
	 * @param title Window name.
	 */
	public void initialize(int ySize, int xSize, String title) {
		terminal = new CursesLikeAPI(new SwingTerminal());
		terminal.init(title, ySize, xSize);
		
		buffer = new CursesLikeAPI(new UnboundTerminal());
		buffer.init("buffer", ySize, xSize);
		
		palette = new ColorPalette();
		//palette_.putMapping(ColorNames.SVG_COLORS);
		
		terminal.setPalette(palette);
		buffer.setPalette(palette);
	}
	
	public void save() {
		buffer.copyFrom(terminal, getYSize(), getXSize(), 0, 0, 0, 0);
		buffer.refresh();
	}
	
	public void restore() {
		terminal.copyFrom(buffer, getYSize(), getXSize(), 0, 0, 0, 0);
		terminal.refresh();
	}
	
	/**
	 * Refresh the Screen.
	 */
	public void refresh() {
		terminal.doUpdate();
	}
	
	public void setCellColors(int y, int x, Integer fore, Integer back) {
		terminal.set(y, x, null, fore, back);
	}
	
	public Integer getCellBg(int y, int x) {
		return terminal.get(y, x).getBackground();
	}
	
	public Integer getCellFg(int y, int x) {
		return terminal.get(y, x).getForeground();
	}
	
	/**
	 * Display a character.
	 * 
	 * @param ch The character to display.
	 * @param y Y position.
	 * @param x X position.
	 * @param foreground Foreground (text) color.
	 * @param background Background color.
	 */
	public void putch(char ch, int y, int x, String foreground, String background) {
		terminal.setCurForeground(foreground);
		terminal.setCurBackground(background);
		terminal.mvaddch(y, x, ch);
		terminal.move(-1, -1);
		resetColors();
	}
	
	
	
	/**
	 * Display a character.
	 * 
	 * @param ch The character to display.
	 * @param y Y position.
	 * @param x X position.
	 * @param foreground Foreground (text) color.
	 * @param background Background color.
	 */
	public void putch(char ch, int y, int x, int foreground, int background) {
		terminal.setCurForeground(foreground);
		terminal.setCurBackground(background);
		terminal.mvaddch(y, x, ch);
		terminal.move(-1, -1);
		resetColors();
	}
	
	
	
	/**
	 * Display a String.
	 * 
	 * @param str The String to display.
	 * @param y Y position.
	 * @param x X position.
	 * @param foreground Foreground (text) color.
	 * @param background Background color.
	 */
	public void puts(String str, int y, int x, String foreground, String background) {
		terminal.setCurForeground(foreground);
		terminal.setCurBackground(background);
		terminal.mvputs(y, x, str);
		terminal.move(-1, -1);
		resetColors();
	}
	
	
	
	/**
	 * Display a String.
	 * 
	 * @param str The String to display.
	 * @param y Y position.
	 * @param x X position.
	 * @param foreground Foreground (text) color.
	 * @param background Background color.
	 */
	public void puts(String str, int y, int x, int foreground, int background) {
		terminal.setCurForeground(foreground);
		terminal.setCurBackground(background);
		terminal.mvputs(y, x, str);
		terminal.move(-1, -1);
		resetColors();
	}
	
	
	
	/**
	 * Clear the Screen.
	 */
	public void clear() {
		terminal.clear();
		terminal.move(-1, -1);
	}
	
	public void clear(int starty, int startx, int endy, int endx) {
		for (int iy = starty; iy < endy; iy++) {
			for (int ix = startx; ix < endx; ix++) {
				putch(' ', iy, ix, defaultFg, defaultBg);
			}
		}
	}
	
	/**
	 * Get a character. (No echo.)
	 * 
	 * @return character
	 */
	public Integer getch() {
		int ch;
		if (ParallelRL.realTime) {
			ch = terminal.getch(0);
		} else {
			ch = terminal.getch();
		}
		
		if (ch != 983040 && (ch & 0x100000) == 0x100000
				&& terminal.keyWaiting()) {
			int ch2 = getch();
			ch ^= ch2;
		}
		while (terminal.keyWaiting()) {
			ch = terminal.getch();				// Clear the keypress buffer
		}
		
		
		return ch;
	}
	
	
	
	/**
	 * Get a user-inputted String.
	 * 
	 * @param length Length of input to get.
	 * @return
	 */
	public String gets(int length) {
		return terminal.gets(length);
	}
	
	
	public String prompt(String pString) {
		terminal.setCurForeground(defaultFg);
		terminal.setCurBackground(defaultBg);
		terminal.mvputs(Config.windowSize.y - 1, 0, pString);
		String rString = gets(-1);
		terminal.move(-1, -1);
		return rString;
	}
	
	private void resetColors() {
		terminal.setCurForeground(defaultFg);
		terminal.setCurBackground(defaultBg);
	}
	
	public void rhetoricalPrompt(String pString, int color) {
		terminal.setCurForeground(color);
		terminal.setCurBackground(defaultBg);
		terminal.mvputs(Config.windowSize.y - 1, 0, pString);
		terminal.move(-1, -1);
		resetColors();
	}
	
	/**
	 * @return Number of rows.
	 */
	public int getYSize() {
		return terminal.getHeight();
	}
	
	
	
	/**
	 * @return Number of columns.
	 */
	public int getXSize() {
		return terminal.getWidth();
	}
	
	
	public Integer getDefaultBg() {
		return defaultBg;
	}
	
	public Integer getDefaultFg() {
		return defaultFg;
	}
	
	
	

}
